# https://www.bookstack.cn/read/python-3.10.0-zh/ee9fd3d3216a3836.md


a = 20
print(type(a))    # 可以查看a的类型

# int可以根据表示的数据的大小 自动扩容 所以不需要long
# float可以是双精度浮点数 所以不需要double
# python中只有字符串类型 没有字符类型 ’‘和”“都可以表示字符串

# python是动态类型的，程序运行过程中，变量的类型可能会发生改变

# 下面的是多行注释
"""
qqq
1222
855
"""

a = 10
print(f"a={a}")   # 希望数字和字符串打印出来 结果为“a=10"

# 输入：   input执行时会等待用户输入
num = input("请输入： ")
# 输出
print(f"输入的是：{num}")

# / 除
print(7/2)   # 3.5
# // 地板除法（取整除法）
print(7//2)  # 3

print(0.1+0.2)  # 不是得到0.3 而是得到0.3000000000000004

a = 0.1+0.2
b = 0.3
print(-0.00001 < (a-b) < 0.000001)  # 在一定范围内就可以正确  并且python是可以连续比较的

a, b = 10, 20  # 多元负责  a=10,b=20
a, b = b, a   # 多元赋值，交换两个变量的值

# python不支持++或者--的自增自减操作

# python中的缩进很重要  代表代码块 并且可以使用缩进嵌套

# input里输入的都是字符串类型 所以需要给它转换一下为int  就可以进行运算
a = input("输入：")
a = int(a)

# 在python中负数%2是正数  如：-19%2=1


# python表示循环的是while和for


# 定义函数
# def 函数名(形参列表)：
#     函数体
#     return 返回值     -----不是必须的

# 定义一个求和函数
def calcSum(beg,end):
    theSum=0
    for i in range(beg, end+1):
        theSum+=i
    print(theSum)

# python 中规定 函数在前 调用在后

# 第一次调用的时候 才开始执行函数

# 嵌套调用的层次可以有很多层

# 函数栈帧

# 给函数定义一个debug 设置默认值为false
# 如果传入的值为True，则打印（辅助调试） 如果不传入，则默认为false
def add(x,y,debug=False):      #debug只能在后面 非默认参数要放前面，有默认参数放后面
    if debug:
        print(f"x={x},y={y}")
    return x+y

# result = add(10,20,)
# print(result)
# add(x=10,y=20,debug=True)  # 明确表示 值传给哪个参数


# python的列表和元组，可以用一个变量表示很多个数据----------相当于“数组”
# 列表可变：创建好后，可以修改
# 元组不可变：创建好后，改不了，想改的话只能丢弃旧的，搞个新的

# 创建列表  1
a = []
print(type(a))
# 创建列表  2
b = list()
print(type(b))

# 可以创建列表时，指定初始值,可以放不同类型
a= [1,2,"qqq",True]
print(a)
print(a[2])  # 这个是指下标2 从0开始计数

#修改指定下标的值
a=[1,2,3,4]
a[2]=100
print(a)

# 可以使用内建函数 len 来获取列表的长度(元素的个数），和字符串相似
a= [1,2,"qqq",True]
print(len(a))

# python的下标可以写成负数----->a[-1]等价于a[len(a)-1]
a= [1,2,"qqq",True]
print(a[len(a)-1])
print(a[-1])



# 切片操作  [1:3] 表示1~3的一段区间（包含1不包含3）--》前闭后开

a=[1,2,3,4]
print(a[1:3])
print(a[1:])  # 可省略后边界 一直取到整个列表结束
print(a[:2])  # 可省略前边界，从0开始到2结束
print(a[:])   # 都省略 则为列表自身

# 切片操作是高效的操作，只是取出源列表的一部分 不涉及”数据拷贝“
print(a[::2])      # 2为步长，每隔2个元素取一个
print(a[1:-1:2])   #--》从下标1到len(a)-1，每两个元素取一个


# 遍历列表 ---for
for elem in a:     # elem代表列表里的每个元素
    print(elem)
# 遍历列表 ---for,通过下标方式
for i in range(0,len(a)):
    print(a[i])
#遍历列表 ---while循环，通过下标遍历
i=0
while i<len(a):
    print(a[i])
    i+=1


# 使用apped 往列表末尾新增一个元素
a.append(5)
a.append('bbb')
print(a)
# 使用insert方法往列表的任意位置来新增元素,若下标超过长度，则直接插入末尾
a.insert(1,"hhh")
print(a)


# 使用 in 来判定某个元素是否在某个列表存在(not in就是不存在）
a=[1,2,3,4]
print(1 in a)
print(20 in a)
print(20 not in a)

# 使用 index 方法来判定，当前元素在列表中的位置 得到一个下标
a=[1,2,3,4]
print(a.index(2))



a=[1,2,3,4]
# 使用pop 删除列表的最末尾的元素
a.pop()
print(a)
# 使用 pop 也可以删除任意元素位置，pop传下标过去
a.pop(1)
print(a)


# 使用remove方法，可以按照值来删除
a=['aa','bb','cc']
a.remove('bb')
print(a)


# 使用 + 针对两个列表进行拼接(生成一个新的大的列表，，但是原来列表不变）
a=[1,2,3,4]
b=[5,6,7,8]
c=a+b
print(c)


# 使用extend来进行拼接
# 这个拼接是把后一个列表的内容拼接大奥一个新的列表里面
a=[1,2,3,4]
b=[5,6,7,8]
a.extend(b)
print(a)
print(b)

# 使用+=来进行拼接
a=[1,2,3,4]
b=[5,6,7,8]
a+=b     # 和extend有区别 这个是a=a+b
print(a)
print(b)



# 创建元组
a=()
print(type(a))
b=tuple()
print(type(b))
# 指定初始值 -->可以任意类型
a=(1,2,'a',4)
print(a)
# 通过元组下标来访问元素，从0开始到len-1结束 （和列表一样）
a=(1,2,3,4)
print(a[1])
# 元组和列表一样 可以使用for等等
# 元组支持读操作  不支持修改操作


# 当进行多元赋值时，其实本质上是按照元组的方式来进行工作
def getPoint():
    x=10
    y=20
    return x,y

x,y=getPoint()
print(type(getPoint()))


# 创建字典---->键值对  'key':value     本质上是哈希表
a={'id':1,'name':'lisan'}     # 方法1---初始时最好格式化：多行方式
print(type(a))
print(a)
b=dict()     #方法2
print(type(b))

a={
    'id':1,
    'name':'zhangsan',
    100:'list'   # 这个100是key value 是'list'
}
# 使用 in 来判定某个key 是否在字典中存在（not in判断不存在)
print('id' in a)
print('classId' in a)
print('zhangsan' in a)    # in 只判断key 不判断value
# 使用 [] 来根据key获取到value
print(a['id'])
print(a['name'])
print(a[100])

# 字典中新增元素 使用[]进行 --》 插入新的键值对
a['score']=90
print(a)
# 在字典中根据key修改value  也是使用[] 进行的
a['score']=100
print(a)

# 使用pop方法，根据key 来删除键值对
a.pop('name')
print(a)

# 字典中的遍历
for key in a:
    print(key, a[key])
# python中遍历的顺序和插入的顺序一致
# keys是获取到字典中的所有key
print(a.keys())    # 返回的结果是一个自定义的类型--dict_keys
# values是获取到字典中的所有value
print(a.values())
# item获取到字典中的所有键值对
print(a.items())


# 使用hash  哈希函数能够计算出一个变量的哈希值
print(hash(0))
print(hash(3.14))
print(hash("a"))
print(hash(True))
print(hash((1,2,3)))
# 有些类型是不可计算哈希值的   --->列表和字典不可 但是元组可以


# 文件
# 目录名使用\分割 /也可以

# python有一个机制 垃圾回收---自动把不使用的变量，进行释放

# 打开文件   open
f = open('d:/leidian/test.txt', 'r')    # r  -->read    w  ->write
print(f)
print(type(f))
# 直接写‘w’打开，然后关闭，会把文件原有内容清空
# 追加方式打开 ‘a' 则不会清空，可以在后面追加内容

# 写文件时，需要使用 w 打开 如果使用r 打开则抛异常
# 写文件   write
f.write('hello')

# 读文件  read
f = open('d:/leidian/test.txt', 'r',encoding='utf8')    # 使用utf8编码
# 这是读几个字
result = f.read(5)
#  按行读取
# for line in f:
#     (f'line={line}', end='')
#    print(f'line = {line}')  # 会多一个空行  因为末尾默认为\n

# 使用readlines方法 把整个文件所有内容读取出来，按照行组织到一个列表里
lines = f.readlines()
print(lines)

# 关闭文件  close    ---文件打开后一定要关闭，释放资源！！！
f.close()      # 若不关闭 可能导致资源泄露



# 使用上下文管理器来解决问题 ----- 解决代码块里有语句retrun了但是没有执行f的close
# 当with对应的代码块执行结束，会自动执行f的close
# def func():
#     with open('d:/leidian/test.txt','r',encoding='utf8') as f:
#         # 进行文件处理的逻辑
#         # 假设有很多代码（里面存在 条件判断 里面有return）


# 库有两类
# 标准库：Python自带库
# 第三方库：大佬做的
